<?php
namespace app\common\library;

use think\Log;

class Sfkuaidi
{
    private static $_appId     = 'GZSZYW1_XGG';
    private static $_appSecret = 'f19e1c929a76201566a56ee96584c65b';
    private static $_custid    = '8511394106';

    /**
     * 下单接口获取运单号URL
     */
//    const CREATE_URL = 'https://voucher.sit.sf-express.com/api/api/route/v1/place'; //测试
    const CREATE_URL = 'https://voucher.inn.sf-express.com/api/api/route/v1/place'; //正式

//    const CANCEL_URL = 'https://voucher.sit.sf-express.com/api/api/route/v1/cancel'; //测试
    const CANCEL_URL = 'https://voucher.inn.sf-express.com/api/api/route/v1/cancel'; //正式

//    const QUERY_ROUTE = 'https://voucher.sit.sf-express.com/api/api/route/v1/queryRoute'; //测试
    const QUERY_ROUTE = 'https://voucher.inn.sf-express.com/api/api/route/v1/queryRoute'; //正式


    /**
     * 下单接口获取运单号
     *
     * @param array [outOrderNo,senderContact,senderTel,senderAddress ...]
     *
     * @return void
     *  [
     *    'returnCode' => 'SUCCESS' // FALSE
     *    'mailNo' => "SF1310740041328" //returnCode为SUCCESS时存在；运单号
     *    'outOrderNo' => '20220801135849001' //returnCode为SUCCESS时存在；订单号：三方系统单号，在第三方系统中唯一
     *    'sfOrderNo' => '20220801135849001' //returnCode为SUCCESS时存在；顺丰系统单号，顺丰系统唯一
     *  ]
     *
     * {"appId":"API_TEST","mailNo":"SF1310740041328","outOrderNo":"20220801135849001","returnCode":"SUCCESS","sfOrderNo":"20220801135849001"}
     */
    public static function create($data)
    {
        $sign = md5(self::$_appId . $data['outOrderNo'] . $data['senderTel'] . $data['recipientTel'] . self::$_appSecret);
        $params = [
            'appId' => self::$_appId,

            'outOrderNo' => $data['outOrderNo'], //订单号，不能重复
            'senderContact' => $data['senderContact'], //寄件人姓名
            'senderTel' => $data['senderTel'], //寄件人联系⽅方式
            'senderAddress' => $data['senderAddress'], //寄件人详细地址若省市区不填，则传入完整寄件地址

            'recipientContact' => $data['recipientContact'], // 收件人姓名
            'recipientTel' => $data['recipientTel'], //收件人联系⽅方式,
            'recipientAddress' => $data['recipientAddress'],// 收件⼈详细地址若省市区不填，则传入完整寄件地址
            'custid' => self::$_custid, //顺丰月结卡号
            'payMethod' => '1',
            'cargo' => $data['cargo'],
            'sign'  => strtolower($sign),
        ];

        // 判断是省外空运
        if (!empty($data['province']) && $data['province'] === '贵州省'){
            $params['expressType'] = '2';
        }else{
            $params['expressType'] = '112';
        }

        $timestamp = time();
        $sign_header = self::getSign($timestamp);
        $res_json = self::http_post(self::CREATE_URL, json_encode($params, JSON_UNESCAPED_UNICODE), $sign_header, $timestamp);
        return json_decode($res_json, true);
    }

    /**
     * 取消订单
     * @param $outOrderNo
     * @return mixed
     *
     * {
         "appId": "API_TEST",
         "errorCode": "10001",
         "errorMsg": "订单已揽件无法取消",
         "outOrderNo": "2022080449989999",
         "returnCode": "FALSE"
        }
     *
     * {
         "appId": "API_TEST",
         "data": "取消成功",
         "outOrderNo": "2022080555505252",
         "returnCode": "SUCCESS"
        }
     */
    public static function cancel($outOrderNo)
    {
        $params = [
            'appId'      => self::$_appId,
            'outOrderNo' => $outOrderNo,
            'sfOrderNo'  => $outOrderNo,
            'signType'   => 'MD5'
        ];
        $params['sign'] = strtolower(md5(self::$_appId . $params['outOrderNo'] . $params['sfOrderNo'] . self::$_appSecret));

        $timestamp = time();
        $sign_header = self::getSign($timestamp);
        $res_json = self::http_post(self::CANCEL_URL, json_encode($params), $sign_header, $timestamp);
        $res_arr = json_decode($res_json, true);

        // 不存在的视为已取消
        if (is_array($res_arr) && !empty($res_arr['errorMsg']) && strpos($res_arr['errorMsg'], '在库里不存在') !== false )
        {
            return true;
        }
        if (is_array($res_arr) && !empty($res_arr['returnCode']) && $res_arr['returnCode'] == 'SUCCESS')
        {
            return true;
        }
        return false;
    }

    /**
     * 查询物流信息
     * @param $outOrderNo
     * @param $mailNo
     * @return mixed
     */
    public static function queryRoute($outOrderNo, $mailNo)
    {
        $params = [
            'appId'      => self::$_appId,
            'outOrderNo' => $outOrderNo,
            'sfOrderNo'  => $outOrderNo,
            'mailNo'     => $mailNo,
            'signType'   => 'MD5'
        ];
        $params['sign'] = strtolower(md5(self::$_appId . $params['outOrderNo'] . $params['sfOrderNo'] . self::$_appSecret));

        $timestamp = time();
        $sign_header = self::getSign($timestamp);
        $res_json = self::http_post(self::QUERY_ROUTE, json_encode($params), $sign_header, $timestamp);
        return json_decode($res_json, true);
    }

    /**
     * 获取公共签名
     * @param $timestamp
     * @return string
     */
    private static function getSign($timestamp)
    {
        $sign = md5($timestamp . '|' . self::$_appId . '|' . self::$_appSecret . '|' . $timestamp);
        return strtolower($sign);
    }

    /**
     * POST请求
     */
    private static function http_post($url, $params, $sign, $timestamp)
    {
        Log::write('请求顺丰地址：'.$url.' 数据：'.$params, 'sf-info');
        $oCurl = curl_init();
        curl_setopt($oCurl, CURLOPT_HTTPGET, true);
        if (stripos($url, 'https://') !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
        }

        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        $headers = array(
            'Content-Type: application/json; charset=UTF-8',
            'appId: ' . self::$_appId,
            'sign: ' . $sign,
            'timestamp: ' . $timestamp
        );
        curl_setopt($oCurl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $params);

        //true 时追踪句柄的请求字符串，从 PHP 5.1.3 开始可用。这个很关键，就是允许你查看请求header
        //curl_setopt($oCurl, CURLINFO_HEADER_OUT, true);

        $response = curl_exec($oCurl);

        //echo curl_getinfo($oCurl, CURLINFO_HEADER_OUT);

        curl_close($oCurl);
        Log::write('顺丰返回数据：'.$response, 'sf-info');
        return $response;
    }

}